package com.atguigu.annoaop;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.stereotype.Component;

import java.lang.reflect.Array;
import java.util.Arrays;

// 切面类
@Aspect
@Component // 给ioc容器bean管理
public class LogAspect {
    // 设置切入点和通知类型
//    @Before(value = "execution(* com.atguigu.annoaop.*(..))")
    @Before(value="execution( public int com.atguigu.annoaop.CalculatorImpl.*(..))")
    public void beforeMethod( ) {
        System.out.println("前置通知");
    }

    @After(value="execution( public int com.atguigu.annoaop.CalculatorImpl.*(..))")
    public void afterMethod(JoinPoint joinPoint) {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("后置方法："+methodName+",参数："+ Arrays.toString(args));
    }

    // ------------- 返回通知
    @AfterReturning(value="execution( public int com.atguigu.annoaop.CalculatorImpl.*(..))",
            returning="result")
    public void afterReturning(JoinPoint joinPoint, Object result) {}

    // ------------- 异常通知
    @AfterThrowing(value="execution( public int com.atguigu.annoaop.CalculatorImpl.*(..))",
            throwing="ex")
    public void afterThrowMethod(JoinPoint joinPoint, Throwable ex) {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("异常方法："+methodName+",参数："+ Arrays.toString(args));
    }

    // ------------- 环绕通知 所有通知的前后
    @Around(value="pointCut()")
    public Object aroundMethod(ProceedingJoinPoint joinPoint) throws Throwable {
        String methodName = joinPoint.getSignature().getName();
        Object[] args = joinPoint.getArgs();
        System.out.println("环绕方法："+methodName+",参数："+ Arrays.toString(args));
        Object result = joinPoint.proceed();
        System.out.println("环绕完成");
        return result;
    }

    // 重用切入点表达式
    @Pointcut(value="execution( public int com.atguigu.annoaop.CalculatorImpl.*(..))")
    public void pointCut() {}

}
